﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using SlViewMetadata = SmartSpace.UI.Silverlight.Web.Metadatas.ViewMetadata;
using SlFieldMetadata = SmartSpace.UI.Silverlight.Web.Metadatas.FieldMetadata;
using SlData = SmartSpace.UI.Silverlight.Web.Datas.DataInstance;
using SlField = SmartSpace.UI.Silverlight.Web.Datas.FieldInstance;
using SlAttachment = SmartSpace.UI.Silverlight.Web.Datas.Attachment;
using SlDictionaryData = SmartSpace.UI.Silverlight.Web.Datas.DictionaryData;
using SlOrg = SmartSpace.UI.Silverlight.Web.Datas.Org;
using SlWfDriveLog = SmartSpace.UI.Silverlight.Web.Datas.WfDriveLog;
using SlWfEvent = SmartSpace.UI.Silverlight.Web.Metadatas.WorkflowEvent;
using SlUser = SmartSpace.UI.Silverlight.Web.Datas.User;
using WFUser = SmartSpace.UI.Silverlight.Web.Datas.WorkflowUser;

using SmartSpace.Core;
using SmartSpace.Data;
using SmartSpace.Workflow;
using System.Web.Script.Serialization;
using System.Text;

namespace SmartSpace.UI.Silverlight.Web
{
    /// <summary>
    /// Summary description for DynamicWebService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class DynamicWebService : System.Web.Services.WebService
    {
        #region Metadata

        [WebMethod]
        public SingleResult<SlViewMetadata> GetViewMetadata(
            Guid workflowId,
            Guid activityId,
            int viewType,
            int wfState,
            string userName)
        {
            ICoreService service = Global.Get<ICoreService>();
            User user = service.FindUser(userName);
            if (user != null)
            {
                IWorkflowService wfService = Global.Get<IWorkflowService>();
                WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
                ActivityMetadata activity = workflow.Get(activityId);
                SmartSpace.Data.ViewMetadata view = wfService.GetView(
                    activity, 
                    (WfViewType)Enum.Parse(typeof(WfViewType), viewType.ToString()),
                    (WfState)Enum.Parse(typeof(WfState), wfState.ToString()),
                    user);

                SlViewMetadata viewMetadata = new SlViewMetadata();
                viewMetadata.Caption = view.Caption;
                viewMetadata.CanModify = view.CanModify;
                viewMetadata.CanRemove = view.CanRemove;

                for (int i = 0; i < view.Fields.Count; i++)
                {
                    FieldMetadata fieldMetadata = view.Fields[i];

                    SlFieldMetadata field = new SlFieldMetadata();
                    field.ID = fieldMetadata.Id;
                    field.Name = fieldMetadata.Property.Name;
                    field.Caption = fieldMetadata.Property.Caption;
                    field.Type = fieldMetadata.Property.Type.Name;
                    if (!string.IsNullOrEmpty(fieldMetadata.Property.TypeFlag))
                    {
                        field.TypeFlag = new Guid(fieldMetadata.Property.TypeFlag);
                    }
                    field.OrderIndex = fieldMetadata.OrderIndex;
                    field.CanVisit = fieldMetadata.CanVisit;
                    field.CanModify = fieldMetadata.CanModify;
                    viewMetadata.FieldMetadatas.Add(field);
                }

                //viewMetadata.StatusMetadatas = GetStatus(tableName, user);

                return new SingleResult<SlViewMetadata>(true, "获取成功!", viewMetadata);
            }
            return new SingleResult<SlViewMetadata>(true, "获取失败，用户不存在!", null);
        }

        #endregion

        [WebMethod]
        public PagedResult<SlData> GetListData(
            Guid workflowId,
            Guid activityId,
            int status,
            string userName,
            int start,
            int limit)
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(userName);

            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);

            PagedList<DataInstance> datas = wfService.GetDatas(
                workflow,
                activity,
                WfViewType.List,
                (WfState)Enum.Parse(typeof(WfState), status.ToString()),
                user,
                start,
                limit);

            List<SlData> items = new List<SlData>();
            for (int index = 0; index < datas.Count; index++)
            {
                SlData item = new SlData();
                item.Id = datas[index].Id;
                foreach (var fieldData in datas[index].Fields)
                {
                    SlField fieldItem = new SlField();
                    fieldItem.Id = fieldData.Property.Id;
                    fieldItem.Name = fieldData.Property.Name;
                    fieldItem.Type = fieldData.Property.Type.Name;
                    fieldItem.Text = fieldData.Text;
                    fieldItem.Value = fieldData.Value;
                    item.Fields.Add(fieldItem);
                }
                items.Add(item);
            }

            PagedResult<SlData> result = new PagedResult<SlData>(
                datas.Start,
                datas.Limit,
                datas.Total,
                items);

            return result;
        }

        [WebMethod]
        public SingleResult<SlData> GetData(Guid workflowId, Guid activityId, Guid dataId)
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);
            ViewMetadata view = wfService.GetView(activity, WfViewType.Detail, WfState.Processing, user);
            DataInstance instance = wfService.GetData(view, user, dataId);

            SlData data = new SlData();
            data.Id = instance.Id;
            data.Fields = new List<SlField>();

            foreach (var fieldInstance in instance.Fields)
            {
                SlField fieldData = new SlField();
                fieldData.Id = fieldInstance.Property.Id;
                fieldData.Name = fieldInstance.Property.Name;
                fieldData.Value = fieldInstance.Value;
                fieldData.Text = fieldInstance.Text;
                fieldData.Type = fieldInstance.Property.Type.Name;
                data.Fields.Add(fieldData);
            }
            return new SingleResult<SlData>(true, "success!", data);
        }

        [WebMethod]
        public SingleResult<SlData> SaveData(
            Guid workflowId,
            Guid activityId,
            SlData data)
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);
            ViewMetadata view = wfService.GetView(activity, WfViewType.Detail, WfState.Processing, user);
            DataInstance instance = wfService.GetData(view, user, data.Id);

            foreach (var fieldInstance in instance.Fields)
            {
                foreach (var fieldData in data.Fields)
                {
                    // 系统类型的字段不能通过界面修改
                    if (!fieldInstance.Property.Type.IsSystem
                        && fieldData.Id == fieldInstance.Property.Id)
                    {
                        if (fieldInstance.Property.Type.IsComplex)
                        {
                            FieldInstance.SetData(fieldInstance, fieldData.Value, fieldData.Text);
                        }
                        else
                        {
                            FieldInstance.SetData(fieldInstance, fieldData.Value);
                        }
                        break;
                    }
                }
            }

            DataInstance resultData = wfService.Save(view, instance, user);
            if (resultData != null)
            {
                data.Id = resultData.Id;

                foreach (var fieldData in data.Fields)
                {
                    foreach (var fieldInstance in resultData.Fields)
                    {
                        if (fieldData.Id == fieldInstance.Property.Id)
                        {
                            fieldData.Value = fieldInstance.Value;
                            break;
                        }
                    }
                }
                return new SingleResult<SlData>(true, "success!", data);
            }
            else
            {
                return new SingleResult<SlData>(false, "保存失败!", null);
            }
        }

        /// <summary>
        /// 获取数据可以被驱动的事件
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="activityId"></param>
        /// <param name="dataId"></param>
        /// <returns></returns>
        [WebMethod]
        public ListResult<SlWfEvent> GetEvents(Guid workflowId, Guid activityId, Guid dataId)
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);
            List<EventMetadata> eventMetadatas = wfService.GetEvents(activity, null, user);

            List<SlWfEvent> wfEvents = new List<SlWfEvent>();
            foreach (var item in eventMetadatas)
            {
                SlWfEvent wfEvent = new SlWfEvent();
                wfEvent.Id = item.Id;
                wfEvent.Caption = item.Caption;
                wfEvent.OrderIndex = item.OrderIndex;
                wfEvent.Type = item.Type.Name;
                wfEvents.Add(wfEvent);
            }

            return new ListResult<SlWfEvent>(wfEvents);
        }

        [WebMethod]
        public ListResult<WFUser> GetEventReceivers(Guid workflowId, Guid activityId, Guid eventId)
        {
            List<WFUser> receivers = new List<WFUser>();

            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);
            EventMetadata @event = workflow.GetEvent(eventId);
            List<WorkflowUser> models = wfService.GetEventReceivers(@event, user);

            foreach (var model in models)
            {
                WFUser receiver = new WFUser();
                receiver.Id = model.Id;
                receiver.Account = model.Account;
                receiver.Name = model.Name;
                receiver.RoleId = model.RoleId;
                receiver.RoleName = model.RoleName;
                receiver.OrgId = model.OrgId;
                receiver.OrgName = model.OrgName;
                receivers.Add(receiver);
            }

            return new ListResult<WFUser>(receivers);
        }

        [WebMethod]
        public ServiceResult Drive(Guid workflowId, Guid activityId, Guid eventId, Guid dataId, List<Guid> receiverIds)
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            WorkflowMetadata workflow = wfService.FindWorkflow(workflowId);
            ActivityMetadata activity = workflow.Get(activityId);
            EventMetadata @event = workflow.GetEvent(eventId);

            //List<User> receivers = coreService.FindUsers(receiverIds);

            if (wfService.Drive(workflow, activity, @event, dataId, user, receiverIds))
            {

                return new ServiceResult();
            }
            else
            {
                return new ServiceResult(false, "流程流转失败!");
            }
        }

        [WebMethod]
        public ListResult<SlAttachment> GetAttachments()
        {
            return null;
        }

        #region dictionary
        [WebMethod]
        public ListResult<SlDictionaryData> GetDictionaryDatas(Guid typeId)
        {
            IDataService service = Global.Get<IDataService>();
            List<DictionaryData> datas = service.FindDictionaryDatas(typeId);
            List<SlDictionaryData> list = new List<SlDictionaryData>();

            foreach (var item in datas)
            {
                list.Add(Convert(item));
            }

            return new ListResult<SlDictionaryData>(list);
        }

        private SlDictionaryData Convert(DictionaryData data)
        {
            SlDictionaryData result = new SlDictionaryData();
            result.Id = data.Id;
            result.Caption = data.Caption;
            result.OrderIndex = data.OrderIndex;
            result.Children = new List<SlDictionaryData>();
            if (data.Children != null && data.Children.Count > 0)
            {
                foreach (var item in data.Children)
                {
                    result.Children.Add(Convert(item));
                }
            }
            return result;
        }
        #endregion

        #region Org

        [WebMethod]
        public ListResult<SlOrg> GetOrgs()
        {
            ICoreService coreService = Global.Get<ICoreService>();
            IWorkflowService wfService = Global.Get<IWorkflowService>();

            User user = coreService.FindUser(this.User.Identity.Name);
            List<Org> orgs = coreService.FindOrgs(null, true);
            List<SlOrg> result = new List<SlOrg>();
            foreach (var item in orgs)
            {
                result.Add(Convert(item));
            }

            return new ListResult<SlOrg>(result);
        }

        private SlOrg Convert(Org data)
        {
            SlOrg result = new SlOrg();
            result.Id = data.Id;
            result.Caption = data.Caption;
            result.OrderIndex = data.OrderIndex;
            result.Children = new List<SlOrg>();
            if (data.Children != null && data.Children.Count > 0)
            {
                foreach (var item in data.Children)
                {
                    result.Children.Add(Convert(item));
                }
            }
            return result;
        }

        #endregion

        #region User

        [WebMethod]
        public ListResult<SlUser> GetUsers()
        {
            return null;
        }

        #endregion

        #region WorkflowRecord

        [WebMethod]
        public ListResult<SlWfDriveLog> GetWorkflowRecords(Guid workflowId, Guid dataId)
        {
            List<SlWfDriveLog> records = new List<SlWfDriveLog>();

            IWorkflowService wfService = Global.Get<IWorkflowService>();
            List<WfDriveLog> items = wfService.GetDriveHistories(wfService.GetInstance(workflowId, dataId));
            foreach (var item in items)
            {
                SlWfDriveLog record = new SlWfDriveLog();
                record.EventId = item.EventId;
                record.Event = item.Event;
                record.DriveDate = item.DriveDate;
                record.FromId = item.FromId;
                record.From = item.From;
                record.ToId = item.ToId;
                record.To = item.To;
                record.ActivityId = item.ActivityId;
                record.Activity = item.Activity;
                record.IsActivated = item.IsActivated;
                record.Children = new List<SlWfDriveLog>();

                foreach (var subItem in item.Items)
                {
                    SlWfDriveLog subRecord = new SlWfDriveLog();
                    subRecord.EventId = subItem.EventId;
                    subRecord.Event = subItem.Event;
                    subRecord.DriveDate = subItem.DriveDate;
                    subRecord.FromId = subItem.FromId;
                    subRecord.From = subItem.From;
                    subRecord.ToId = subItem.ToId;
                    subRecord.To = subItem.To;
                    subRecord.ActivityId = subItem.ActivityId;
                    subRecord.Activity = subItem.Activity;
                    subRecord.IsActivated = subItem.IsActivated;
                    record.Children.Add(subRecord);
                }

                records.Add(record);
            }

            return new ListResult<SlWfDriveLog>(records);
        }

        #endregion

        [WebMethod]
        public SingleResult<string> Get(string cmd, string data)
        {
            // 获取本公司下面的部门
            if (cmd == "0-1-1")
            {
                ICoreService coreService = Global.Get<ICoreService>();
                IWorkflowService wfService = Global.Get<IWorkflowService>();

                User user = coreService.FindUser(this.User.Identity.Name);
                List<Org> orgs = coreService.FindOrgs(null, true);
                JavaScriptSerializer jss = new JavaScriptSerializer();
                StringBuilder stringBuilder = new StringBuilder();
                jss.Serialize(orgs, stringBuilder);
                return new SingleResult<string>(true,"", stringBuilder.ToString());
            }
            return new SingleResult<string>(false, "获取失败", "");
        }
    }
}
